// arch-tag: 751ad4b5-6349-4d91-8e4d-e67cce3f43e8
package de.yvert.jingle.tools;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.*;
import java.awt.image.BufferedImage;

import javax.swing.*;

import de.yvert.jingle.ToneMapper;
import de.yvert.jingle.hdr.HdrImage2D;
import de.yvert.jingle.ldr.LdrImage2D;

public class ImageViewer
{

	static class MyCanvas extends JComponent
	{
		private static final long serialVersionUID = 1L;
		ImageViewer viewer;
		@Override
		public void paint(Graphics g)
		{
			if (!viewer.done) viewer.updateImage();
			g.drawImage(viewer.bimg, 0, 0, this);
		}
		public MyCanvas(ImageViewer viewer)
		{
			this.viewer = viewer;
			setPreferredSize(new Dimension(viewer.image.getWidth(), viewer.image.getHeight()));
		}
	}

private int width;
private int height;
private JFrame frame;
private HdrImage2D image;
private LdrImage2D outputImage;
private ToneMapper toneMapper = new ClampToneMapper();
private BufferedImage bimg;
private MyCanvas canvas;

private boolean done = false;

public ImageViewer(HdrImage2D image, String title)
{
	init(image, title);
	updateImage();
	done = true;
	frame.setVisible(true);
}

public void close()
{
	frame.dispose();
}

public void switchFilter(ToneMapper newMapper)
{
	toneMapper = newMapper;
	updateImage();
	canvas.repaint();
}

private void updateImage()
{
	toneMapper.map(image, outputImage);
	
	int[] data = new int[outputImage.getWidth()*outputImage.getHeight()];
	outputImage.encodeARGBint(data);
	bimg.setRGB(0, 0, outputImage.getWidth(), outputImage.getHeight(), data, 0, outputImage.getWidth());
}

CustomAction closeAction = new CustomAction("Close")
	{
		public void actionPerformed(ActionEvent event)
		{ close(); }
	};

CustomAction switchToDirectAction = new CustomAction("Direct")
	{
		public void actionPerformed(ActionEvent event)
		{ switchFilter(new ClampToneMapper()); }
	};

CustomAction switchToNormalizeAction = new CustomAction("Normalize")
	{
		public void actionPerformed(ActionEvent event)
		{ switchFilter(new NormalizeToneMapper()); }
	};

CustomAction switchToAverageAction = new CustomAction("Average = 0.75")
	{
		public void actionPerformed(ActionEvent event)
		{ switchFilter(new AverageToneMapper()); }
	};

private void put(ActionMap actionMap, InputMap inputMap, CustomAction action)
{
	actionMap.put(action.getName(), action);
	KeyStroke accelerator = action.getAccelerator();
	if (accelerator != null) inputMap.put(accelerator, action.getName());
}

private void init(HdrImage2D newImage, String newTitle)
{
	image = newImage;
	outputImage = new LdrImage2D(newImage.getWidth(), newImage.getHeight());
	width = newImage.getWidth();
	height = newImage.getHeight();
	
	bimg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
	canvas = new MyCanvas(this);
	
	// Set accelerator keys
//	saveAction.setAccelerator(KeyStroke.getKeyStroke('S', InputEvent.CTRL_MASK));
	closeAction.setAccelerator(KeyStroke.getKeyStroke('W', InputEvent.ALT_MASK));
	
	switchToDirectAction.setAccelerator(KeyStroke.getKeyStroke('D', InputEvent.ALT_MASK));
	
	switchToNormalizeAction.setAccelerator(KeyStroke.getKeyStroke('N', InputEvent.ALT_MASK));
	
	switchToAverageAction.setAccelerator(KeyStroke.getKeyStroke('A', InputEvent.ALT_MASK));
	
	// Create popup menu
	final JPopupMenu popupMenu = new JPopupMenu();
	canvas.add(popupMenu);
	
//	popupMenu.add(new JMenuItem(saveAction));
//	popupMenu.addSeparator();
	popupMenu.add(new JMenuItem(switchToDirectAction));
	popupMenu.add(new JMenuItem(switchToNormalizeAction));
	popupMenu.add(new JMenuItem(switchToAverageAction));
	
	
	// Create frame
	frame = new JFrame(newTitle);
	frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
	frame.setResizable(false);
//	frame.setLocationByPlatform(true);
	frame.setLocation(100, 100);
	frame.add(canvas);
	
	
	// Initialize input & action maps
	ActionMap actionMap = ((JComponent) frame.getContentPane()).getActionMap();
	InputMap inputMap = ((JComponent) frame.getContentPane()).getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
	
	put(actionMap, inputMap, closeAction);
//	put(actionMap, inputMap, saveAction);
	put(actionMap, inputMap, switchToDirectAction);
	put(actionMap, inputMap, switchToNormalizeAction);
	
	
	// Additional input mappings
	String closeName = closeAction.getName();
	inputMap.put(KeyStroke.getKeyStroke('Q', InputEvent.ALT_MASK), closeName);
	inputMap.put(KeyStroke.getKeyStroke('Q', 0), closeName);
	inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), closeName);
	
	
	// Add popup trigger
	canvas.addMouseListener(new MouseAdapter()
		{
			public boolean triggerPopup(MouseEvent event)
			{
				if (event.isPopupTrigger())
				{
					popupMenu.show(event.getComponent(), event.getX(), event.getY());
					event.consume();
					return true;
				}
				return false;
			}
			@Override
			public void mouseClicked(MouseEvent event)
			{
				if (triggerPopup(event)) return;
				event.consume();
				System.out.println("Mouse clicked at "+event.getX()+" "+event.getY());
			}
			@Override
			public void mousePressed(MouseEvent event)
			{ if (triggerPopup(event)) return; }
			@Override
			public void mouseReleased(MouseEvent event)
			{ if (triggerPopup(event)) return; }
		});
	
	
	// Allow frame to initialize itself
	frame.pack();
}

}
